package com.spt.springbootzhsx.service;

import cn.hutool.core.codec.Base64;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.spt.springbootzhsx.entity.Admin;
import com.spt.springbootzhsx.entity.User;
import com.spt.springbootzhsx.entity.back.LoginBack;
import com.spt.springbootzhsx.entity.wx.WxLogin;
import com.spt.springbootzhsx.entity.wx.WxUser;
import com.spt.springbootzhsx.mapper.AdminMapper;
import com.spt.springbootzhsx.mapper.UserMapper;
import com.spt.springbootzhsx.redis.RedisOp;
import com.spt.springbootzhsx.utils.DateUtil;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class LoginImpl implements LoginService{
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private AdminMapper adminMapper;
    @Autowired
    private RedisOp redisOp;

    @Override  //用户普通登录
    public LoginBack UserLogin(Integer uid, String password) {
        LoginBack loginBack=new LoginBack();
        loginBack.setMsg("false");
        User user=userMapper.getUserByUid(uid);
        if(user!=null){  //账号存在
            if(user.getPassword().equals(password)){  //判断密码是否正确
                user.setAddTime(DateUtil.formatDate(user.getAddTime()));
                loginBack.setObj(user);
                loginBack.setMsg("true");
            }
        }
        return loginBack;
    }

    @Override  //管理员普通登录
    public Admin AdminLogin(Integer aid, String password) {
        LoginBack loginBack=new LoginBack();
        Admin admin=adminMapper.getAdminByAid(aid);
        if(admin!=null){ //管理员账号存在
            if(admin.getPassword().equals(password)){
                return admin;
            }
        }
        return null;
    }



    @Override
    public String getSessionId(String code) {
        String appid = "wx4ad1b9c4ded27552";
        String secret = "dd121dee46b91b8e9a30ce8061bfcd95";
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid="+appid+"&secret="+secret+"&js_code="+code+"&grant_type=authorization_code";
        String res= HttpUtil.get(url);
        String uuid= UUID.randomUUID().toString();
        redisOp.set("sessionId"+uuid,res,30);
        return uuid;
    }

    @Override
    public LoginBack getToken(WxLogin wxLogin) {
        String json=wxDecrypt(wxLogin.getEncrytedData(),wxLogin.getIv(),wxLogin.getSessionId());
        JSONObject jsonObject=JSON.parseObject(json);
        //获取sessionKey和openid
        JSONObject jsonObject1=JSONObject.parseObject(redisOp.get("sessionId"+wxLogin.getSessionId()));
        String sessionKey=(String) jsonObject1.get("session_key");
        String openid=(String) jsonObject1.get("openid");
        WxUser wxUser=JSON.parseObject(json,WxUser.class);
        String token=UUID.randomUUID().toString();  //生成token令牌
        User user=userMapper.getUserByOpenId(openid);
        LoginBack loginBack=new LoginBack();
        if(user==null){
            //无微信绑定的用户，先注册
            user=new User();
            user.setOpenid(openid);
            SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date=new Date();
            String time=simpleDateFormat.format(date);
            try {
                user.setAddTime(simpleDateFormat.parse(time));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            user.setGender(wxUser.getGender());
            user.setUsername(wxUser.getNickName());
            userMapper.addUser(user);
            User newuser=userMapper.getUserByOpenId(openid);
            user.setUid(newuser.getUid());
            //将token作为键值将openid、sessionKey和unionId存入Redis
            redisOp.set("token"+token,openid+";"+sessionKey+";"+wxUser.getUnionId(),7*24*60);
            //封装返回数据
            user.setOpenid(null);   //openid前端需要用token换取
            loginBack.setObj(user);
            loginBack.setToken(token);
        }else{
            //已有微信绑定的用户
            //将token作为键值将openid、sessionKey和unionId存入Redis(更新缓存时间）
            redisOp.set("token"+token,openid+";"+sessionKey+";"+wxUser.getUnionId(),30*24*60);
            user.setOpenid(null);   //openid前端需要用token换取
            loginBack.setToken(token);
            loginBack.setObj(user);
        }
        return loginBack;
    }

    public String wxDecrypt(String encryptedData, String vi, String sessionId) {
        String json=redisOp.get("sessionId"+sessionId);
        JSONObject jsonObject= JSON.parseObject(json);
        String sessionKey=(String) jsonObject.get("session_key");
        byte[] encData=cn.hutool.core.codec.Base64.decode(encryptedData);
        byte[] iv=cn.hutool.core.codec.Base64.decode(vi);
        byte[] key= Base64.decode(sessionKey);
        AlgorithmParameterSpec ivSpec=new IvParameterSpec(iv);
        try {
            Cipher cipher=Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec keySpec=new SecretKeySpec(key,"AES");
            cipher.init(Cipher.DECRYPT_MODE,keySpec,ivSpec);
            return new String(cipher.doFinal(encData),"UTF-8");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return "解密异常";
    }


}
